render: Rename gtkborderimage.[ch]
authorBenjamin Otte <otte@redhat.com>
Sat, 17 Jan 2015 17:00:03 +0000 (18:00 +0100)
committerBenjamin Otte <otte@redhat.com>
Tue, 20 Jan 2015 05:30:18 +0000 (06:30 +0100)
I want the gtkrender prefix for all filenames about rendering.

gtk/Makefile.am
gtk/deprecated/gtkstyleproperties.c
gtk/gtkborderimage.c [deleted file]
gtk/gtkborderimageprivate.h [deleted file]
gtk/gtkrender.c
gtk/gtkrenderborder.c [new file with mode: 0644]
gtk/gtkrenderborderprivate.h [new file with mode: 0644]

index 4c9f2443badcde74856eb76da25b3a7de8cc1a08..0deed771ce58a3188908cf89b39c64578de5dcd8 100644 (file)
@@ -353,7 +353,6 @@ gtk_private_h_sources =             \
        gtkbitmaskprivate.h     \
        gtkbitmaskprivateimpl.h \
        gtkbookmarksmanager.h   \
-       gtkborderimageprivate.h \
        gtkboxprivate.h         \
        gtkbuilderprivate.h     \
        gtkbuttonprivate.h      \
@@ -478,6 +477,7 @@ gtk_private_h_sources =             \
        gtkrecentchooserprivate.h \
        gtkrecentchooserutils.h \
        gtkrenderbackgroundprivate.h \
+       gtkrenderborderprivate.h \
        gtkrenderprivate.h      \
        gtkresources.h          \
        gtkroundedboxprivate.h  \
@@ -554,7 +554,6 @@ gtk_base_c_sources =                \
        gtkbindings.c           \
        gtkbookmarksmanager.c   \
        gtkborder.c             \
-       gtkborderimage.c        \
        gtkbox.c                \
        gtkbuildable.c          \
        gtkbuilder.c            \
@@ -762,6 +761,7 @@ gtk_base_c_sources =                \
        gtkrecentmanager.c      \
        gtkrender.c             \
        gtkrenderbackground.c   \
+       gtkrenderborder.c       \
        gtkresources.c          \
        gtkrevealer.c           \
        gtkroundedbox.c         \
index 9cf29754eea96fbf5b96a2831afec97d757905e1..291260d91cec93add4c36c6642131ff8e19e8ab0 100644 (file)
@@ -27,7 +27,6 @@
 #include "gtkcssshorthandpropertyprivate.h"
 #include "gtkcsstypedvalueprivate.h"
 #include "gtkcsstypesprivate.h"
-#include "gtkborderimageprivate.h"
 
 #include "gtkprivatetypebuiltins.h"
 #include "gtkstylepropertyprivate.h"
diff --git a/gtk/gtkborderimage.c b/gtk/gtkborderimage.c
deleted file mode 100644 (file)
index 58a43f8..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * Authors: Carlos Garnacho <carlosg@gnome.org>
- *          Cosimo Cecchi <cosimoc@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <config.h>
-#include <cairo-gobject.h>
-
-#include <math.h>
-
-#include "gtkborderimageprivate.h"
-#include "gtkcssbordervalueprivate.h"
-#include "gtkcssimagevalueprivate.h"
-#include "gtkcssnumbervalueprivate.h"
-#include "gtkcssrepeatvalueprivate.h"
-#include "gtkcssstyleprivate.h"
-
-/* this is in case round() is not provided by the compiler, 
- * such as in the case of C89 compilers, like MSVC
- */
-#include "fallback-c89.c"
-
-gboolean
-_gtk_border_image_init (GtkBorderImage *image,
-                        GtkCssStyle    *style)
-{
-  image->source = _gtk_css_image_value_get_image (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE));
-  if (image->source == NULL)
-    return FALSE;
-
-  image->slice = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE);
-  image->width = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH);
-  image->repeat = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT);
-
-  return TRUE;
-}
-
-typedef struct _GtkBorderImageSliceSize GtkBorderImageSliceSize;
-struct _GtkBorderImageSliceSize {
-  double offset;
-  double size;
-};
-
-static void
-gtk_border_image_compute_border_size (GtkBorderImageSliceSize  sizes[3],
-                                      double                   offset,
-                                      double                   area_size,
-                                      double                   start_border_width,
-                                      double                   end_border_width,
-                                      const GtkCssValue       *start_border,
-                                      const GtkCssValue       *end_border)
-{
-  double start, end;
-
-  if (_gtk_css_number_value_get_unit (start_border) == GTK_CSS_NUMBER)
-    start = start_border_width * _gtk_css_number_value_get (start_border, 100);
-  else
-    start = _gtk_css_number_value_get (start_border, area_size);
-  if (_gtk_css_number_value_get_unit (end_border) == GTK_CSS_NUMBER)
-    end = end_border_width * _gtk_css_number_value_get (end_border, 100);
-  else
-    end = _gtk_css_number_value_get (end_border, area_size);
-
-  /* XXX: reduce vertical and horizontal by the same factor */
-  if (start + end > area_size)
-    {
-      start = start * area_size / (start + end);
-      end = end * area_size / (start + end);
-    }
-
-  sizes[0].offset = offset;
-  sizes[0].size = start;
-  sizes[1].offset = offset + start;
-  sizes[1].size = area_size - start - end;
-  sizes[2].offset = offset + area_size - end;
-  sizes[2].size = end;
-}
-
-static void
-gtk_border_image_render_slice (cairo_t           *cr,
-                               cairo_surface_t   *slice,
-                               double             slice_width,
-                               double             slice_height,
-                               double             x,
-                               double             y,
-                               double             width,
-                               double             height,
-                               GtkCssRepeatStyle  hrepeat,
-                               GtkCssRepeatStyle  vrepeat)
-{
-  double hscale, vscale;
-  double xstep, ystep;
-  cairo_extend_t extend = CAIRO_EXTEND_PAD;
-  cairo_matrix_t matrix;
-  cairo_pattern_t *pattern;
-
-  /* We can't draw center tiles yet */
-  g_assert (hrepeat == GTK_CSS_REPEAT_STYLE_STRETCH || vrepeat == GTK_CSS_REPEAT_STYLE_STRETCH);
-
-  hscale = width / slice_width;
-  vscale = height / slice_height;
-  xstep = width;
-  ystep = height;
-
-  switch (hrepeat)
-    {
-    case GTK_CSS_REPEAT_STYLE_REPEAT:
-      extend = CAIRO_EXTEND_REPEAT;
-      hscale = vscale;
-      break;
-    case GTK_CSS_REPEAT_STYLE_SPACE:
-      {
-        double space, n;
-
-        extend = CAIRO_EXTEND_NONE;
-        hscale = vscale;
-
-        xstep = hscale * slice_width;
-        n = floor (width / xstep);
-        space = (width - n * xstep) / (n + 1);
-        xstep += space;
-        x += space;
-        width -= 2 * space;
-      }
-      break;
-    case GTK_CSS_REPEAT_STYLE_STRETCH:
-      break;
-    case GTK_CSS_REPEAT_STYLE_ROUND:
-      extend = CAIRO_EXTEND_REPEAT;
-      hscale = width / (slice_width * MAX (round (width / (slice_width * vscale)), 1));
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
-    }
-
-  switch (vrepeat)
-    {
-    case GTK_CSS_REPEAT_STYLE_REPEAT:
-      extend = CAIRO_EXTEND_REPEAT;
-      vscale = hscale;
-      break;
-    case GTK_CSS_REPEAT_STYLE_SPACE:
-      {
-        double space, n;
-
-        extend = CAIRO_EXTEND_NONE;
-        vscale = hscale;
-
-        ystep = vscale * slice_height;
-        n = floor (height / ystep);
-        space = (height - n * ystep) / (n + 1);
-        ystep += space;
-        y += space;
-        height -= 2 * space;
-      }
-      break;
-    case GTK_CSS_REPEAT_STYLE_STRETCH:
-      break;
-    case GTK_CSS_REPEAT_STYLE_ROUND:
-      extend = CAIRO_EXTEND_REPEAT;
-      vscale = height / (slice_height * MAX (round (height / (slice_height * hscale)), 1));
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
-    }
-
-  pattern = cairo_pattern_create_for_surface (slice);
-
-  cairo_matrix_init_translate (&matrix,
-                               hrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? slice_width / 2 : 0,
-                               vrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? slice_height / 2 : 0);
-  cairo_matrix_scale (&matrix, 1 / hscale, 1 / vscale);
-  cairo_matrix_translate (&matrix,
-                          hrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? - width / 2 : 0,
-                          vrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? - height / 2 : 0);
-
-  cairo_pattern_set_matrix (pattern, &matrix);
-  cairo_pattern_set_extend (pattern, extend);
-
-  cairo_save (cr);
-  cairo_translate (cr, x, y);
-
-  for (y = 0; y < height; y += ystep)
-    {
-      for (x = 0; x < width; x += xstep)
-        {
-          cairo_save (cr);
-          cairo_translate (cr, x, y);
-          cairo_set_source (cr, pattern);
-          cairo_rectangle (cr, 0, 0, xstep, ystep);
-          cairo_fill (cr);
-          cairo_restore (cr);
-        }
-    }
-
-  cairo_restore (cr);
-
-  cairo_pattern_destroy (pattern);
-}
-
-static void
-gtk_border_image_compute_slice_size (GtkBorderImageSliceSize sizes[3],
-                                     int                     surface_size,
-                                     int                     start_size,
-                                     int                     end_size)
-{
-  sizes[0].size = MIN (start_size, surface_size);
-  sizes[0].offset = 0;
-
-  sizes[2].size = MIN (end_size, surface_size);
-  sizes[2].offset = surface_size - sizes[2].size;
-
-  sizes[1].size = MAX (0, surface_size - sizes[0].size - sizes[2].size);
-  sizes[1].offset = sizes[0].size;
-}
-
-void
-_gtk_border_image_render (GtkBorderImage   *image,
-                          const double      border_width[4],
-                          cairo_t          *cr,
-                          gdouble           x,
-                          gdouble           y,
-                          gdouble           width,
-                          gdouble           height)
-{
-  cairo_surface_t *surface, *slice;
-  GtkBorderImageSliceSize vertical_slice[3], horizontal_slice[3];
-  GtkBorderImageSliceSize vertical_border[3], horizontal_border[3];
-  double source_width, source_height;
-  int h, v;
-
-  _gtk_css_image_get_concrete_size (image->source,
-                                    0, 0,
-                                    width, height,
-                                    &source_width, &source_height);
-
-  /* XXX: Optimize for (source_width == width && source_height == height) */
-
-  surface = _gtk_css_image_get_surface (image->source,
-                                        cairo_get_target (cr),
-                                        source_width, source_height);
-
-  gtk_border_image_compute_slice_size (horizontal_slice,
-                                       source_width, 
-                                       _gtk_css_number_value_get (_gtk_css_border_value_get_left (image->slice), source_width),
-                                       _gtk_css_number_value_get (_gtk_css_border_value_get_right (image->slice), source_width));
-  gtk_border_image_compute_slice_size (vertical_slice,
-                                       source_height, 
-                                       _gtk_css_number_value_get (_gtk_css_border_value_get_top (image->slice), source_height),
-                                       _gtk_css_number_value_get (_gtk_css_border_value_get_bottom (image->slice), source_height));
-  gtk_border_image_compute_border_size (horizontal_border,
-                                        x,
-                                        width,
-                                        border_width[GTK_CSS_LEFT],
-                                        border_width[GTK_CSS_RIGHT],
-                                        _gtk_css_border_value_get_left (image->width),
-                                        _gtk_css_border_value_get_right (image->width));
-  gtk_border_image_compute_border_size (vertical_border,
-                                        y,
-                                        height,
-                                        border_width[GTK_CSS_TOP],
-                                        border_width[GTK_CSS_BOTTOM],
-                                        _gtk_css_border_value_get_top (image->width),
-                                        _gtk_css_border_value_get_bottom(image->width));
-  
-  for (v = 0; v < 3; v++)
-    {
-      if (vertical_slice[v].size == 0 ||
-          vertical_border[v].size == 0)
-        continue;
-
-      for (h = 0; h < 3; h++)
-        {
-          if (horizontal_slice[h].size == 0 ||
-              horizontal_border[h].size == 0)
-            continue;
-
-          if (h == 1 && v == 1)
-            continue;
-
-          slice = cairo_surface_create_for_rectangle (surface,
-                                                      horizontal_slice[h].offset,
-                                                      vertical_slice[v].offset,
-                                                      horizontal_slice[h].size,
-                                                      vertical_slice[v].size);
-
-          gtk_border_image_render_slice (cr,
-                                         slice,
-                                         horizontal_slice[h].size,
-                                         vertical_slice[v].size,
-                                         horizontal_border[h].offset,
-                                         vertical_border[v].offset,
-                                         horizontal_border[h].size,
-                                         vertical_border[v].size,
-                                         h == 1 ? _gtk_css_border_repeat_value_get_x (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH,
-                                         v == 1 ? _gtk_css_border_repeat_value_get_y (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH);
-
-          cairo_surface_destroy (slice);
-        }
-    }
-
-  cairo_surface_destroy (surface);
-}
diff --git a/gtk/gtkborderimageprivate.h b/gtk/gtkborderimageprivate.h
deleted file mode 100644 (file)
index 90a8326..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * Authors: Carlos Garnacho <carlosg@gnome.org>
- *          Cosimo Cecchi <cosimoc@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GTK_BORDER_IMAGE_H__
-#define __GTK_BORDER_IMAGE_H__
-
-#include "gtkborder.h"
-#include "gtkcssimageprivate.h"
-#include "gtkcssvalueprivate.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GtkBorderImage GtkBorderImage;
-
-struct _GtkBorderImage {
-  GtkCssImage *source;
-
-  GtkCssValue *slice;
-  GtkCssValue *width;
-  GtkCssValue *repeat;
-};
-
-gboolean          _gtk_border_image_init             (GtkBorderImage       *image,
-                                                      GtkCssStyle          *style);
-
-void              _gtk_border_image_render           (GtkBorderImage       *image,
-                                                      const double          border_width[4],
-                                                      cairo_t              *cr,
-                                                      gdouble               x,
-                                                      gdouble               y,
-                                                      gdouble               width,
-                                                      gdouble               height);
-
-G_END_DECLS
-
-#endif /* __GTK_BORDER_IMAGE_H__ */
index 4a95a9cef24595c6612a43677b625b49f2140ffb..0c87401190a95b2515d7324ff2c7a6da04e1b8a2 100644 (file)
@@ -22,7 +22,6 @@
 
 #include <math.h>
 
-#include "gtkborderimageprivate.h"
 #include "gtkcsscornervalueprivate.h"
 #include "gtkcssenginevalueprivate.h"
 #include "gtkcssenumvalueprivate.h"
@@ -34,6 +33,7 @@
 #include "gtkcsstransformvalueprivate.h"
 #include "gtkhslaprivate.h"
 #include "gtkrenderbackgroundprivate.h"
+#include "gtkrenderborderprivate.h"
 #include "gtkstylecontextprivate.h"
 
 #include "fallback-c89.c"
diff --git a/gtk/gtkrenderborder.c b/gtk/gtkrenderborder.c
new file mode 100644 (file)
index 0000000..5a96718
--- /dev/null
@@ -0,0 +1,322 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ *          Cosimo Cecchi <cosimoc@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "gtkrenderborderprivate.h"
+
+#include <cairo-gobject.h>
+#include <math.h>
+
+#include "gtkcssbordervalueprivate.h"
+#include "gtkcssimagevalueprivate.h"
+#include "gtkcssnumbervalueprivate.h"
+#include "gtkcssrepeatvalueprivate.h"
+#include "gtkcssstyleprivate.h"
+
+/* this is in case round() is not provided by the compiler, 
+ * such as in the case of C89 compilers, like MSVC
+ */
+#include "fallback-c89.c"
+
+gboolean
+_gtk_border_image_init (GtkBorderImage *image,
+                        GtkCssStyle    *style)
+{
+  image->source = _gtk_css_image_value_get_image (gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE));
+  if (image->source == NULL)
+    return FALSE;
+
+  image->slice = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE);
+  image->width = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH);
+  image->repeat = gtk_css_style_get_value (style, GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT);
+
+  return TRUE;
+}
+
+typedef struct _GtkBorderImageSliceSize GtkBorderImageSliceSize;
+struct _GtkBorderImageSliceSize {
+  double offset;
+  double size;
+};
+
+static void
+gtk_border_image_compute_border_size (GtkBorderImageSliceSize  sizes[3],
+                                      double                   offset,
+                                      double                   area_size,
+                                      double                   start_border_width,
+                                      double                   end_border_width,
+                                      const GtkCssValue       *start_border,
+                                      const GtkCssValue       *end_border)
+{
+  double start, end;
+
+  if (_gtk_css_number_value_get_unit (start_border) == GTK_CSS_NUMBER)
+    start = start_border_width * _gtk_css_number_value_get (start_border, 100);
+  else
+    start = _gtk_css_number_value_get (start_border, area_size);
+  if (_gtk_css_number_value_get_unit (end_border) == GTK_CSS_NUMBER)
+    end = end_border_width * _gtk_css_number_value_get (end_border, 100);
+  else
+    end = _gtk_css_number_value_get (end_border, area_size);
+
+  /* XXX: reduce vertical and horizontal by the same factor */
+  if (start + end > area_size)
+    {
+      start = start * area_size / (start + end);
+      end = end * area_size / (start + end);
+    }
+
+  sizes[0].offset = offset;
+  sizes[0].size = start;
+  sizes[1].offset = offset + start;
+  sizes[1].size = area_size - start - end;
+  sizes[2].offset = offset + area_size - end;
+  sizes[2].size = end;
+}
+
+static void
+gtk_border_image_render_slice (cairo_t           *cr,
+                               cairo_surface_t   *slice,
+                               double             slice_width,
+                               double             slice_height,
+                               double             x,
+                               double             y,
+                               double             width,
+                               double             height,
+                               GtkCssRepeatStyle  hrepeat,
+                               GtkCssRepeatStyle  vrepeat)
+{
+  double hscale, vscale;
+  double xstep, ystep;
+  cairo_extend_t extend = CAIRO_EXTEND_PAD;
+  cairo_matrix_t matrix;
+  cairo_pattern_t *pattern;
+
+  /* We can't draw center tiles yet */
+  g_assert (hrepeat == GTK_CSS_REPEAT_STYLE_STRETCH || vrepeat == GTK_CSS_REPEAT_STYLE_STRETCH);
+
+  hscale = width / slice_width;
+  vscale = height / slice_height;
+  xstep = width;
+  ystep = height;
+
+  switch (hrepeat)
+    {
+    case GTK_CSS_REPEAT_STYLE_REPEAT:
+      extend = CAIRO_EXTEND_REPEAT;
+      hscale = vscale;
+      break;
+    case GTK_CSS_REPEAT_STYLE_SPACE:
+      {
+        double space, n;
+
+        extend = CAIRO_EXTEND_NONE;
+        hscale = vscale;
+
+        xstep = hscale * slice_width;
+        n = floor (width / xstep);
+        space = (width - n * xstep) / (n + 1);
+        xstep += space;
+        x += space;
+        width -= 2 * space;
+      }
+      break;
+    case GTK_CSS_REPEAT_STYLE_STRETCH:
+      break;
+    case GTK_CSS_REPEAT_STYLE_ROUND:
+      extend = CAIRO_EXTEND_REPEAT;
+      hscale = width / (slice_width * MAX (round (width / (slice_width * vscale)), 1));
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  switch (vrepeat)
+    {
+    case GTK_CSS_REPEAT_STYLE_REPEAT:
+      extend = CAIRO_EXTEND_REPEAT;
+      vscale = hscale;
+      break;
+    case GTK_CSS_REPEAT_STYLE_SPACE:
+      {
+        double space, n;
+
+        extend = CAIRO_EXTEND_NONE;
+        vscale = hscale;
+
+        ystep = vscale * slice_height;
+        n = floor (height / ystep);
+        space = (height - n * ystep) / (n + 1);
+        ystep += space;
+        y += space;
+        height -= 2 * space;
+      }
+      break;
+    case GTK_CSS_REPEAT_STYLE_STRETCH:
+      break;
+    case GTK_CSS_REPEAT_STYLE_ROUND:
+      extend = CAIRO_EXTEND_REPEAT;
+      vscale = height / (slice_height * MAX (round (height / (slice_height * hscale)), 1));
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+
+  pattern = cairo_pattern_create_for_surface (slice);
+
+  cairo_matrix_init_translate (&matrix,
+                               hrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? slice_width / 2 : 0,
+                               vrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? slice_height / 2 : 0);
+  cairo_matrix_scale (&matrix, 1 / hscale, 1 / vscale);
+  cairo_matrix_translate (&matrix,
+                          hrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? - width / 2 : 0,
+                          vrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? - height / 2 : 0);
+
+  cairo_pattern_set_matrix (pattern, &matrix);
+  cairo_pattern_set_extend (pattern, extend);
+
+  cairo_save (cr);
+  cairo_translate (cr, x, y);
+
+  for (y = 0; y < height; y += ystep)
+    {
+      for (x = 0; x < width; x += xstep)
+        {
+          cairo_save (cr);
+          cairo_translate (cr, x, y);
+          cairo_set_source (cr, pattern);
+          cairo_rectangle (cr, 0, 0, xstep, ystep);
+          cairo_fill (cr);
+          cairo_restore (cr);
+        }
+    }
+
+  cairo_restore (cr);
+
+  cairo_pattern_destroy (pattern);
+}
+
+static void
+gtk_border_image_compute_slice_size (GtkBorderImageSliceSize sizes[3],
+                                     int                     surface_size,
+                                     int                     start_size,
+                                     int                     end_size)
+{
+  sizes[0].size = MIN (start_size, surface_size);
+  sizes[0].offset = 0;
+
+  sizes[2].size = MIN (end_size, surface_size);
+  sizes[2].offset = surface_size - sizes[2].size;
+
+  sizes[1].size = MAX (0, surface_size - sizes[0].size - sizes[2].size);
+  sizes[1].offset = sizes[0].size;
+}
+
+void
+_gtk_border_image_render (GtkBorderImage   *image,
+                          const double      border_width[4],
+                          cairo_t          *cr,
+                          gdouble           x,
+                          gdouble           y,
+                          gdouble           width,
+                          gdouble           height)
+{
+  cairo_surface_t *surface, *slice;
+  GtkBorderImageSliceSize vertical_slice[3], horizontal_slice[3];
+  GtkBorderImageSliceSize vertical_border[3], horizontal_border[3];
+  double source_width, source_height;
+  int h, v;
+
+  _gtk_css_image_get_concrete_size (image->source,
+                                    0, 0,
+                                    width, height,
+                                    &source_width, &source_height);
+
+  /* XXX: Optimize for (source_width == width && source_height == height) */
+
+  surface = _gtk_css_image_get_surface (image->source,
+                                        cairo_get_target (cr),
+                                        source_width, source_height);
+
+  gtk_border_image_compute_slice_size (horizontal_slice,
+                                       source_width, 
+                                       _gtk_css_number_value_get (_gtk_css_border_value_get_left (image->slice), source_width),
+                                       _gtk_css_number_value_get (_gtk_css_border_value_get_right (image->slice), source_width));
+  gtk_border_image_compute_slice_size (vertical_slice,
+                                       source_height, 
+                                       _gtk_css_number_value_get (_gtk_css_border_value_get_top (image->slice), source_height),
+                                       _gtk_css_number_value_get (_gtk_css_border_value_get_bottom (image->slice), source_height));
+  gtk_border_image_compute_border_size (horizontal_border,
+                                        x,
+                                        width,
+                                        border_width[GTK_CSS_LEFT],
+                                        border_width[GTK_CSS_RIGHT],
+                                        _gtk_css_border_value_get_left (image->width),
+                                        _gtk_css_border_value_get_right (image->width));
+  gtk_border_image_compute_border_size (vertical_border,
+                                        y,
+                                        height,
+                                        border_width[GTK_CSS_TOP],
+                                        border_width[GTK_CSS_BOTTOM],
+                                        _gtk_css_border_value_get_top (image->width),
+                                        _gtk_css_border_value_get_bottom(image->width));
+  
+  for (v = 0; v < 3; v++)
+    {
+      if (vertical_slice[v].size == 0 ||
+          vertical_border[v].size == 0)
+        continue;
+
+      for (h = 0; h < 3; h++)
+        {
+          if (horizontal_slice[h].size == 0 ||
+              horizontal_border[h].size == 0)
+            continue;
+
+          if (h == 1 && v == 1)
+            continue;
+
+          slice = cairo_surface_create_for_rectangle (surface,
+                                                      horizontal_slice[h].offset,
+                                                      vertical_slice[v].offset,
+                                                      horizontal_slice[h].size,
+                                                      vertical_slice[v].size);
+
+          gtk_border_image_render_slice (cr,
+                                         slice,
+                                         horizontal_slice[h].size,
+                                         vertical_slice[v].size,
+                                         horizontal_border[h].offset,
+                                         vertical_border[v].offset,
+                                         horizontal_border[h].size,
+                                         vertical_border[v].size,
+                                         h == 1 ? _gtk_css_border_repeat_value_get_x (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH,
+                                         v == 1 ? _gtk_css_border_repeat_value_get_y (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH);
+
+          cairo_surface_destroy (slice);
+        }
+    }
+
+  cairo_surface_destroy (surface);
+}
diff --git a/gtk/gtkrenderborderprivate.h b/gtk/gtkrenderborderprivate.h
new file mode 100644 (file)
index 0000000..ab0bc74
--- /dev/null
@@ -0,0 +1,54 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
+ * Copyright (C) 2011 Red Hat, Inc.
+ *
+ * Authors: Carlos Garnacho <carlosg@gnome.org>
+ *          Cosimo Cecchi <cosimoc@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_RENDER_BORDER_H__
+#define __GTK_RENDER_BORDER_H__
+
+#include "gtkborder.h"
+#include "gtkcssimageprivate.h"
+#include "gtkcssvalueprivate.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GtkBorderImage GtkBorderImage;
+
+struct _GtkBorderImage {
+  GtkCssImage *source;
+
+  GtkCssValue *slice;
+  GtkCssValue *width;
+  GtkCssValue *repeat;
+};
+
+gboolean          _gtk_border_image_init             (GtkBorderImage       *image,
+                                                      GtkCssStyle          *style);
+
+void              _gtk_border_image_render           (GtkBorderImage       *image,
+                                                      const double          border_width[4],
+                                                      cairo_t              *cr,
+                                                      gdouble               x,
+                                                      gdouble               y,
+                                                      gdouble               width,
+                                                      gdouble               height);
+
+G_END_DECLS
+
+#endif /* __GTK_RENDER_BORDER_H__ */